package com.alibaba.citrus.ots.sales.plan.facade.msg;

import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.util.DateUtils;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.SalesPlanWriteService;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.audit.SalesPlanAdjustSendWxMessageService;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.CreateSalesPlanTemplateRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.QuerySalesPlanRequest;
import com.alibaba.citrus.ots.sales.plan.facade.service.statistics.stat.customer.CustomerStatService;
import com.alibaba.citrus.ots.sales.plan.facade.service.statistics.stat.model.SalesPlanStatRequest;
import com.alibaba.citrus.ots.sales.plan.msg.SalesPlanMessageConsumer;
import com.alibaba.citrus.ots.sales.plan.repository.PlatformEnhanceRepository;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanRepository;
import com.alibaba.citrus.ots.sales.plan.repository.WxAppletRepository;
import com.alibaba.citrus.ots.sales.plan.repository.request.*;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.cz.base.tool.UUIDUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.contants.BcOtsConstants;
import com.epoch.app.bcots.model.dto.EmployeeSDO;
import com.epoch.app.bcots.model.dto.MessageChannelResponse;
import com.epoch.app.bcots.model.dto.MessageTemplateResponse;
import com.epoch.app.bcots.model.dto.WcAppletSubInfoResponse;
import com.epoch.app.otsplatformenhance.api.employeequery.dto.GetEmployeesByOrgIdAndRoleIdEsRequest;
import com.epoch.app.otsplatformenhance.api.employeequery.service.EmployeeQueryService;
import com.epoch.app.otsplatformenhance.enums.OrganizationTypeEnum;
import com.epoch.app.otsplatformenhance.enums.RoleCodeEnum;
import com.epoch.app.otsplatformenhance.sdo.OrganizationSDO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.alibaba.citrus.ots.common.util.DateUtils.DATETIME_FORMAT;

/**
 * @author luyi
 * @date 2021/12/14 8:50 下午
 */
@Component
public class SalesPlanAdjustSendMessageImpl implements SalesPlanAdjustSendWxMessageService {

    public static final String ADJUST_BIZ_TYPE = "salesPlanAdjust";
    private final Log log = Log.getLogger(SalesPlanAdjustSendMessageImpl.class);

    @Resource
    private SalesPlanWriteService salesPlanWriteService;

    @Resource
    private SalesPlanRepository salesPlanRepository;

    @Resource
    private PlatformEnhanceRepository platformEnhanceRepository;

    @Resource
    private WxAppletRepository wxAppletRepository;

    @Autowired
    private EmployeeQueryService employeeQueryService;

    /**
     * 计划明细page_size
     */
    private static final Integer SALES_PLAN_LIN_PAGE_SIZE = 500;

    private static final String ADJUST_EVENT_CODE = "SALES_PLAN_ADJUST";

    private final static List<Integer> statusList = Lists.newArrayList(1);

    @FacadeInvoker
    @Override
    //与月度计划提报发送微信小程序通知代码重复，需要进行重构，将微信小程序单独封装，与月度计划无关
    public void sendWxSubscribeMessage(String planId) {
        QuerySalesPlanRequest querySalesPlanRequest = new QuerySalesPlanRequest();
        querySalesPlanRequest.setId(planId);
        SalesPlanSDO salesPlanSDO = salesPlanRepository.load(querySalesPlanRequest);
        if (null == salesPlanSDO) {
            log.error("sendWxSubscribeMessage_loadPlanInfo_Failed: {}", planId);
            throw new FacadeException("OTS-02-002-00-16-001");
        }

        if (StringUtils.isBlank(BcOtsConstants.WX_APP_ID())) {
            log.warn("未配置小程序id");
            return;
        }
        // 微信消息是弱依赖，不阻断主流程
        try {
            // 获取消息渠道信息
            MessageChannelResponse channelResponse = fetchMessageChannel(BcOtsConstants.WX_APP_ID());
            if (null == channelResponse) {
                log.warn("fetchMessageChannel_Failed,{}",BcOtsConstants.WX_APP_ID());
                return;
            }
            // 获取微信模板
            List<MessageTemplateResponse> messageTemplateResponses = fetchMessageTemplate(channelResponse.getId());
            if (CollectionUtils.isEmpty(messageTemplateResponses)) {
                log.warn("fetchMessageTemplate_Failed,{}",channelResponse.getId());
                return;
            }
            // 获取角色对应的员工信息
            Map<String, EmployeeSDO> employeeSDOMap = fetchEmployeesByRole(salesPlanSDO.getOrgBusinessUnitCode(), OrganizationTypeEnum.SALES_DEPARTMENT.getCode(), RoleCodeEnum.SALE_MAN.getCode());
            if (MapUtils.isEmpty(employeeSDOMap)) {
                log.warn("fetchEmployeesByRole_Failed:{}", salesPlanSDO.getOrgBusinessUnitCode());
                return;
            }
            // 发送微信消息
            log.info("sendWxMessage template:{}, planID:{}, employee:{}",
                    JSONObject.toJSONString(messageTemplateResponses.get(0)), planId, JSONObject.toJSONString(employeeSDOMap));
            sendWxMessage(messageTemplateResponses.get(0), salesPlanSDO, planId, employeeSDOMap);
        } catch (Exception e) {
            log.error("sendWxSubscribeMessage_Failed:", e);
        }
    }

    private Map<String, EmployeeSDO> fetchEmployeesByRole(String organizationId, Integer type, String roleCode) {
        OrganizationListQueryRequest queryRequest = new OrganizationListQueryRequest();
        queryRequest.setId(organizationId);
        queryRequest.setType(type);
        List<OrganizationSDO> organizationSDOList = platformEnhanceRepository.getDownOrganizationList(queryRequest);
        if (CollectionUtils.isEmpty(organizationSDOList)) {
            return null;
        }
        Map<String, EmployeeSDO> employeeSDOMap = Maps.newHashMap();
        organizationSDOList.forEach(organizationSDO -> {
            GetEmployeesByOrgIdAndRoleIdEsRequest request = new GetEmployeesByOrgIdAndRoleIdEsRequest();
            request.setRoleCode(roleCode);
            request.setOrganizationId(organizationSDO.getId());
            Result<List<EmployeeSDO>> result = employeeQueryService.getEmployeesByOrgIdAndRoleIdEs(request);
            if (null == result || CollectionUtils.isEmpty(result.getResult())) {
                return;
            }
            employeeSDOMap.putAll(result.getResult().stream().collect(Collectors.toMap(EmployeeSDO::getId, Function.identity())));
        });
        return employeeSDOMap;
    }

    private MessageChannelResponse fetchMessageChannel(String appId) {
        MessageChannelQueryRequest queryRequest = new MessageChannelQueryRequest();
        queryRequest.setType(2);
        queryRequest.setStatus(1);
        queryRequest.setRemoteMessageChannelId(appId);
        return wxAppletRepository.queryMessageChannel(queryRequest);
    }

    private List<MessageTemplateResponse> fetchMessageTemplate(String channelId) {
        MessageTemplatePageQueryRequest pageQueryRequest = new MessageTemplatePageQueryRequest();
        pageQueryRequest.setEventCode(ADJUST_EVENT_CODE);
        pageQueryRequest.setChannelType(2);
        pageQueryRequest.setChannelId(channelId);
        pageQueryRequest.setStatus(1);
        pageQueryRequest.setStart(0);
        pageQueryRequest.setLimit(1);
        return wxAppletRepository.pageQueryMessageTemplate(pageQueryRequest);
    }

    private void sendWxMessage(MessageTemplateResponse response, SalesPlanSDO salesPlanSDO, String planId, Map<String, EmployeeSDO> map) {
        int page = 1;
        PageResult<List<WcAppletSubInfoResponse>> pageResult = fetchWcAppletSubUserList(response.getChannelId(), response.getChannelTemplateId(), page);
        while (null != pageResult) {
            pageResult.getContent().forEach(wcAppletSubInfoResponse -> {
                doSendWxMessage(wcAppletSubInfoResponse, salesPlanSDO, planId, map);
            });
            if (pageResult.getContent().size() < SALES_PLAN_LIN_PAGE_SIZE) {
                // 已经是最后一页
                break;
            }
            pageResult = fetchWcAppletSubUserList(response.getChannelId(), response.getChannelTemplateId(), ++page);
        }
    }

    private void doSendWxMessage(WcAppletSubInfoResponse response, SalesPlanSDO salesPlanSDO, String planId, Map<String, EmployeeSDO> map) {
        if (MapUtils.isEmpty(response.getFeatures())) {
            log.warn("openId:{}没有传入必要参数", response.getOpenId());
            return;
        }
        String employeeId = response.getFeatures().get("employeeId");
        if (StringUtils.isBlank(employeeId)) {
            log.warn("openId:{}没有传入必要参数", response.getOpenId());
            return;
        }
        if (null == map.get(employeeId)) {
            log.warn("用户:{}订阅微信模板消息，但不是消息送达人", employeeId);
            return;
        }
        if (response.getCount() < 1) {
            log.warn("用户:{}已经没有订阅次数了", employeeId);
            return;
        }

        WxAppletMessageSendRequest sendRequest = new WxAppletMessageSendRequest();
        sendRequest.setBizType(ADJUST_BIZ_TYPE);
        sendRequest.setBizId(UUIDUtil.newWithoutMinus());
        sendRequest.setEventCode(ADJUST_EVENT_CODE);
        sendRequest.setTargetType(2);
        // 如果能取到openId，则不用填写
        sendRequest.setTargetId(null);
        Map<String, String> receivers = Maps.newHashMap();
        // key 取值为 ChannelTypeEnum.WECHAT_APPLET.name()
        receivers.put("WECHAT_APPLET", response.getOpenId());
        sendRequest.setReceivers(receivers);
        Map<String, String> params = Maps.newHashMap();
        buildParam(params, salesPlanSDO, planId);
        sendRequest.setParams(params);
        log.info("sendWxAppletMessage_Adjust_info:{}", JSONObject.toJSONString(sendRequest));
        if (!wxAppletRepository.sendWxAppletMessage(sendRequest)) {
            log.error("发送微信消息失败");
        }
    }

    private void buildParam(Map<String, String> params, SalesPlanSDO salesPlanSDO, String planId) {
        String planTime = DateUtils.stampToDate(salesPlanSDO.getPlanTime());
        try {
            salesPlanSDO.setFormatPlanTime(DateUtils.formatPlanTime(planTime));
        } catch (Exception e) {
            e.printStackTrace();
        }
        params.put("planId", planId);
        params.put("salesPlanName", salesPlanSDO.getFormatPlanTime());
        params.put("reportStartTime", DateUtils.formatDate(salesPlanSDO.getStartTime(), DATETIME_FORMAT));
        params.put("reportEndTime", DateUtils.formatDate(salesPlanSDO.getEndTime(), DATETIME_FORMAT));
    }

    private PageResult<List<WcAppletSubInfoResponse>> fetchWcAppletSubUserList(String channelId, String templateId, int i) {
        SubWxTempInfoUserQueryRequest queryRequest = new SubWxTempInfoUserQueryRequest();
        queryRequest.setTemplateId(templateId);
        queryRequest.setChannelId(channelId);
        queryRequest.setPage(i);
        queryRequest.setSize(SALES_PLAN_LIN_PAGE_SIZE);
        PageResult<List<WcAppletSubInfoResponse>> pageResult = wxAppletRepository.queryWcAppletSubUserList(queryRequest);
        if (null == pageResult || CollectionUtils.isEmpty(pageResult.getContent())) {
            return null;
        }
        return pageResult;
    }
}
